%name eng_simple_

%include {
    global $CFG;
    require_once($CFG->dirroot . '/blocks/formal_langs/tokens_base.php');
    require_once($CFG->dirroot . '/blocks/formal_langs/tokens/eng_simple.php');
 }

%include_class {
    public $error;
    public $ast;
    public $success = false;

    public $dump_info = '';
    
    private $debug_mode = false;
    private $node_num = 0;

    public function set_debug_mode($flag) {
        $this->debug_mode = $flag;
    }

    public function dump() {
        if ($this->debug_mode) {
            ob_start();
            $this->dump_info .= "Stack dump:\n";
            var_dump($this->yystack);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();

            ob_start();
            $this->dump_info .= "$this->list dump:\n";
            var_dump($this->ast);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();

            ob_start();
            $this->dump_info .= "$this->error dump:\n";
            var_dump($this->error);
            $this->dump_info .= ob_get_contents();
            ob_end_clean();
        }
    }

    public function process_token($token) {
        $this->doParse($token->type(), $token);
    }
}

%parse_failure {
    if ($this->debug_mode) {
        $this->dump_info .= "Parsing error.\n";
        $this->dump();
    }
    $this->success = false;
 }

%parse_accept {
    if ($this->debug_mode) {
        $this->dump_info .= "Parsing done.\n";
        $this->dump();
    }
    $this->success = true;
 }

%syntax_error {
    if ($this->debug_mode) {
        $this->dump_info .= "Syntax error.\n";
    }
 }

start ::= text(B) . {
    $this->ast = new block_formal_langs_ast(B);
}

text(A) ::= s(B) eos(C) . {
    $result = new block_formal_langs_ast_node_base("text", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
text(A) ::= text(B) s(C) eos(D) . {
    $result = new block_formal_langs_ast_node_base("text", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $result->add_child(D);
    $positions = array(B->position(), C->position(), D->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
s(A) ::= np(B) vp(C) . {
    $result = new block_formal_langs_ast_node_base("s", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
eos(A) ::= PERIOD(B) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("eos", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->set_position(B->position());
    A = $result;
}
eos(A) ::= EXCLAMATION(B) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("eos", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->set_position(B->position());
    A = $result;
}
eos(A) ::= QUESTION(B) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("eos", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->set_position(B->position());
    A = $result;
}
np(A) ::= DT(B) N(C) . {
    B->set_number($this->node_num++);
    C->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("np", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
np(A) ::= N(B) pp(C) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("np", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
vp(A) ::= V(B) np(C) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("vp", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
vp(A) ::= V(B) pp(C) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("vp", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
vp(A) ::= V(B) np(C) pp(D) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("vp", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $result->add_child(D);
    $positions = array(B->position(), C->position(), D->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
pp(A) ::= P(B) np(C) . {
    B->set_number($this->node_num++);
    $result = new block_formal_langs_ast_node_base("pp", NULL, $this->node_num++, false);
    $result->add_child(B);
    $result->add_child(C);
    $positions = array(B->position(), C->position());
    $result->set_position(block_formal_langs_node_position::summ($positions));
    A = $result;
}
